//
//Copyright (c) 2004 BroadVision, Inc. All rights reserved.
//
//This software is copyrighted.  Under the copyright laws, this software
//may not be copied, in whole or in part, without prior written consent
//of BroadVision, Inc. or its assignees.  This software is provided under
//the terms of a license between BroadVision and the recipient, and its
//use is subject to the terms of that license.
//
//This software may be protected by one or more U.S. and International
//patents.  Certain applications of BroadVision One-To-One software are
//covered by U.S. patent 5,710,887.
//
//TRADEMARKS: BroadVision and BroadVision One-To-One are registered
//trademarks of BroadVision, Inc., in the United States and the European
//Community, and are trademarks of BroadVision, Inc., in other
//countries.  The BroadVision logo, is a trademark of BroadVision, Inc.,
//in the United States and other countries. Additionally, IONA and Orbix
//are trademarks of IONA Technologies, Ltd.  RSA, MD5, and RC2 are
//trademarks of RSA Data Security, Inc.
//

package com.broadvision.manage.common.tools.action.file;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.io.FileFilter;
import java.lang.reflect.Constructor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.util.LabelValueBean;

import com.broadvision.manage.tools.action.BaseAction;
import com.broadvision.web.util.ViewDynaBean;

/**
* 
*/
public class FilePickerAction extends BaseAction {

  public static final String VIEW_BEAN_NAME = "mtFilePickerView";
  public static String DTO_BEAN_NAME = "mtPathDTO";
  public static String PAGER_BEAN_NAME = "pager";

  /**
   * Implements the action for listing files and folders on the server side.
   * <p> <p>
   * @param mapping <code>ActionMapping</code> object used to select this instance
   * @param form Optional <code>ActionForm</code> bean for this request (if any)
   * @param request <code>HttpServletRequest</code> object to process
   * @param response <code>HttpServletResponse</code> object to process
   * <p> <p>
   * @return <code>ActionForward</code> instance describing where and how
   * control should be forwarded, or null if the response has already been completed
   * <p> <p>
   * @throws Exception if an error occurs
  */
  public ActionForward processExecute(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response)
  throws Exception {
    DynaActionForm theForm = (DynaActionForm)form;
    String rootDirectory = theForm.getString("selectedContext");
    String currentDirectory = theForm.getString("selectedDirectory");
    String headerKey = theForm.getString("headerKey");
    String headerBundle = theForm.getString("headerBundle");
    String header = "";
    if (headerKey != null && headerKey.trim().length() > 0) {
      if (headerBundle == null || headerBundle.trim().length() == 0) {
        header = this.getResources(request).getMessage(headerKey);
      }
      else {
        header = this.getResources(request, headerBundle).getMessage(headerKey);
      }
    }
    String parameter = request.getParameter("pager.offset");
    int offset = 0;
    if (parameter != null && parameter.trim().length() > 0) {
      offset = Integer.parseInt(parameter.trim());
    }
    parameter = request.getParameter("pager.maxPageItems");
    int maxPageItems = 10;
    if (parameter != null && parameter.trim().length() > 0) {
      maxPageItems = Integer.parseInt(parameter.trim());
    }
    ViewDynaBean viewBean = new ViewDynaBean(VIEW_BEAN_NAME, mapping);
    request.setAttribute(VIEW_BEAN_NAME, viewBean);
    PropertyUtils.setSimpleProperty(viewBean, "header", header);
    ViewDynaBean pager = new ViewDynaBean(PAGER_BEAN_NAME, mapping);
    request.setAttribute(PAGER_BEAN_NAME, pager);
    File firstContext = buildContextList(mapping, form, request, response, viewBean);
    if (firstContext == null) {
      ActionMessages errors = new ActionMessages();
      errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.file.picker.noRootsConfigured"));
      request.setAttribute(Globals.ERROR_KEY, errors);
      return mapping.findForward("success");
    }
    if (rootDirectory == null || rootDirectory.length() == 0) {
      currentDirectory = firstContext.getCanonicalPath();
      rootDirectory = firstContext.getCanonicalPath();
      PropertyUtils.setSimpleProperty(theForm, "selectedContext", currentDirectory);
      PropertyUtils.setSimpleProperty(theForm, "selectedDirectory", rootDirectory);
      PropertyUtils.setSimpleProperty(theForm, "selectedFile", "");
    }
    else if (currentDirectory == null || currentDirectory.length() == 0) {
      currentDirectory = (String)PropertyUtils.getSimpleProperty(theForm, "selectedContext");
      rootDirectory = (String)PropertyUtils.getSimpleProperty(theForm, "selectedContext");
      PropertyUtils.setSimpleProperty(theForm, "selectedContext", currentDirectory);
      PropertyUtils.setSimpleProperty(theForm, "selectedDirectory", rootDirectory);
      PropertyUtils.setSimpleProperty(theForm, "selectedFile", "");
    }
    else {
      currentDirectory = (String)PropertyUtils.getSimpleProperty(theForm, "selectedDirectory");
      rootDirectory = (String)PropertyUtils.getSimpleProperty(theForm, "selectedContext");
      PropertyUtils.setSimpleProperty(theForm, "selectedFile", "");
    }
    if (rootDirectory == null || rootDirectory.length() == 0 || 
        currentDirectory == null || currentDirectory.length() == 0) {
      ActionMessages errors = new ActionMessages();
      errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.file.picker.noRootsConfigured"));
      request.setAttribute(Globals.ERROR_KEY, errors);
      return mapping.findForward("success");
    }
    File theDir = new File(currentDirectory);
    File theRoot = new File(rootDirectory);
    if (theDir.exists() == false || theDir.isFile() == true || theDir.canRead() == false ||
        theRoot.exists() == false || theRoot.isFile() == true || theRoot.canRead() == false) {
      ActionMessages errors = new ActionMessages();
      errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.file.picker.noRootsConfigured"));
      request.setAttribute(Globals.ERROR_KEY, errors);
      return mapping.findForward("success");
    }
    buildParentFolderList(mapping, form, request, response, viewBean, "currentDirList", 
        theRoot, theDir);
    buildChildFolderList(mapping, form, request, response, viewBean, "subDirList", 
        theDir);
    int count = buildFileList(mapping, form, request, response, viewBean, "fileList", 
        theRoot, theDir, offset, maxPageItems);
    PropertyUtils.setSimpleProperty(pager, "url",  mapping.getPath() + ".do");
    PropertyUtils.setSimpleProperty(pager, "count", new Integer(count));
    PropertyUtils.setSimpleProperty(pager, "maxPageItems", new Integer(maxPageItems));
    Map urlParams = new HashMap();
    PropertyUtils.setSimpleProperty(pager, "urlParams", urlParams);
    urlParams.put("selectedContext", theRoot.getCanonicalPath());
    urlParams.put("selectedDirectory", theDir.getCanonicalPath());
    urlParams.put("callback", (String)PropertyUtils.getSimpleProperty(theForm, "callback"));
    return mapping.findForward("success");
  }

  protected File buildContextList(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response,
      ViewDynaBean view)
  throws Exception {
    ArrayList acList = new ArrayList();
    PropertyUtils.setSimpleProperty(view, "contextList", acList);
    DynaActionForm theForm = (DynaActionForm)form;
    String rootDirectory = theForm.getString("selectedContext");
    if (rootDirectory == null || rootDirectory.trim().length() == 0) {
      return null;
    }
    File topFolder = new File(rootDirectory.trim());
    if (topFolder.exists() == false || topFolder.isFile() == true || topFolder.canRead() == false) {
      return null;
    }
    acList.add(new LabelValueBean(topFolder.getName(), topFolder.getCanonicalPath()));
    return topFolder;
  }

  protected void buildParentFolderList(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response, 
      ViewDynaBean view, String propertyName, File theRoot, File theDir)
  throws Exception {
    ArrayList parents = new ArrayList(1);
    parents.add(theDir);
    File tempFile = theDir;
    while (tempFile.equals(theRoot) == false && tempFile.getParentFile() != null) {
      parents.add(tempFile.getParentFile());
      tempFile = tempFile.getParentFile();
    }
    ArrayList parentList = new ArrayList(parents.size());
    PropertyUtils.setSimpleProperty(view, propertyName, parentList);
    for (int i = parents.size() - 1; i >= 0; i--) {
      tempFile = (File)parents.get(i);
      ViewDynaBean dto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
      dto.set("path", tempFile.getCanonicalPath());
      dto.set("name", tempFile.getName());
      parentList.add(dto);      
    }
  }

  protected void buildChildFolderList(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response, 
      ViewDynaBean view, String propertyName, File theDir)
  throws Exception {
    DynaActionForm theForm = (DynaActionForm)form;
    String filterName = theForm.getString("folderFilter");
    FileFilter theFilter = null;
    if (filterName != null) {
      try {
        Class theClass = Class.forName(filterName);
        Constructor theConstructor = theClass.getConstructor(new Class[0]);
        theFilter = (FileFilter)theConstructor.newInstance(new Object[0]);
      }
      catch (Exception ex) {
        ;
      }
    }
    File[] folders = theDir.listFiles(theFilter == null ? new FolderOnlyFilter() : theFilter);
    if (folders != null && folders.length > 0) {
      ArrayList folderList = new ArrayList(folders.length);
      PropertyUtils.setSimpleProperty(view, propertyName, folderList);
      for (int i = 0; i < folders.length; i++) {
        ViewDynaBean dto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
        dto.set("path", folders[i].getCanonicalPath());
        dto.set("name", folders[i].getName());
        folderList.add(dto);
      }
    }
  }

  protected int buildFileList(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response, 
      ViewDynaBean view, String propertyName, File theRoot, File theDir,
      int offset, int maxPageItems)
  throws Exception {
    DynaActionForm theForm = (DynaActionForm)form;
    String filterName = theForm.getString("fileFilter");
    FileFilter theFilter = null;
    if (filterName != null) {
      try {
        Class theClass = Class.forName(filterName);
        Constructor theConstructor = theClass.getConstructor(new Class[0]);
        theFilter = (FileFilter)theConstructor.newInstance(new Object[0]);
      }
      catch (Exception ex) {
        ;
      }
    }
    File[] folders = theDir.listFiles(theFilter == null ? new FileOnlyFilter() : theFilter);
    if (folders != null && folders.length > 0) {
      ArrayList folderList = new ArrayList();
      PropertyUtils.setSimpleProperty(view, propertyName, folderList);
      for (int i = 0, index = offset; i < maxPageItems && index < folders.length; i++, index++) {
        ViewDynaBean dto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
        dto.set("path", getRelativePath(theRoot, folders[index]));
        dto.set("name", folders[index].getName());
        folderList.add(dto);
      }
      return folders.length;
    }
    return 0;
  }

  protected String getRelativePath(File parent, File child) throws Exception {
    String parentPath = parent.getCanonicalPath();
    String childPath = child.getCanonicalPath();
    if (childPath.indexOf(parentPath) == 0) {
      String relativePath = childPath.substring(parentPath.length());
      return relativePath.replace(File.separatorChar, '/');
    }
    return null;
  }
}

